package com.dht.xiao.jianye.command;

import com.dht.xiao.jianye.base.serialport.DataPack;
import com.dht.xiao.jianye.base.serialport.callback.AsyncDataCallback;
import com.dht.xiao.jianye.base.serialport.utils.ByteUtil;
import com.dht.xiao.jianye.base.util.CRC16Utils;
import com.licheedev.myutils.LogPlus;

import java.nio.ByteBuffer;



/**
 * @author :      fangbingran
 * @aescription : todo(这里用一句话描述这个类的作用)
 * @date :        2019/06/06  17:00
 */
public abstract class VendingMachine3BB3Callback implements AsyncDataCallback {
    private final ByteBuffer mByteBuffer;
    //帧头+机柜地址+ 序号+帧长度+ 控制码+ 数据域+校验码+帧尾（所有命令格式）
    //1、帧长度包括机柜地址到校验的所有字节，不包含帧头帧尾。
    //2/不同的从机如果使用同一个序号变量可能会使从机产在前后两条指令的序号重复
    //主机空闲时应按200-400MS一次的频率不断对从机进行状态轮询。从机应当在最早100US后，最迟100MS后进行回应。
    //主机要对从机发出指令后，从机如果空闲应当立即回应ACK，表示接到指令，并开始执行。执行中，主机可不断以相同的命令格式查询从机的状态，
    // 从机如果还没执行完成则回应BUSY,如果执行完成，以回复相应的执行状态数据,注意序号不能改变

    public VendingMachine3BB3Callback() {
        mByteBuffer = ByteBuffer.allocate(1024);
        mByteBuffer.clear();
    }

    @Override
    public DataPack checkData(byte[] received, int size) {


        try {
            mByteBuffer.put(received, 0, size);
            mByteBuffer.flip();

            byte b;
            int readable;
            byte[] oneBytes = new byte[1];
            byte[] twoBytes = new byte[2];
            // 标记一个第一个元素

            while ((readable = mByteBuffer.remaining()) >= Protocol.MIN_PACK_LEN) {
                mByteBuffer.mark(); // 标记一下开始的位置
                int frameStart = mByteBuffer.position();

                b = mByteBuffer.get();
                if (b != Protocol.FRAME_HEAD_0) { // 第1个byte要AA
                    continue;
                }

                b = mByteBuffer.get();
                if (b != Protocol.FRAME_HEAD_1) { // 第2个byte要66
                    continue;
                }
//
//                // 下一个就是命令长度
                mByteBuffer.position(mByteBuffer.position());

                //AA660311
                //030040A8
                // 数据长度SLEN
                mByteBuffer.get(oneBytes);
              //  LogPlus.e("数据长度=" +  ByteUtil.bytes2HexStr(oneBytes));
                final int slen = (int) ByteUtil.hexStr2decimal(
                    ByteUtil.bytes2HexStr(oneBytes));
//                LogPlus.e("数据长度=" + slen);
                // slen包括command和appdata，所以要把command的1字节减去
                int total = Protocol.MIN_PACK_LEN + slen - 1;
                // 如果可读数据小于总数据长度，表示不够,还有数据没接收
                if (readable < total) {
                    // 重置一下要处理的位置,并跳出循环
                    mByteBuffer.reset();
                    break;
                }
                // 跳过 (COMMAND+APPDATA)=SLEN
                // 找到crc16
                mByteBuffer.position(mByteBuffer.position() + slen);
                mByteBuffer.get(twoBytes);
                String crc16 = ByteUtil.bytes2HexStr(twoBytes).toUpperCase();
                // 回到头
                mByteBuffer.reset();
                // 拿到整个包
                final byte[] data = new byte[total];
                mByteBuffer.get(data);
                String otherCrc16 = CRC16Utils.calcCrc16(ByteUtil.getBytes(data,0,total - 2),  total - 2);

                LogPlus.d("crc16=" + crc16 + ",other_crc16=" + otherCrc16);

                if (crc16.equals(otherCrc16)) {
                    // 校验成功
                    String command = ByteUtil.bytes2HexStr(data, 3, 1);
                    byte[] appdata = new byte[slen];
                    System.arraycopy(data, 3, appdata, 0, appdata.length);

                   LogPlus.e("接受到的命令=" + ByteUtil.bytes2HexStr(data));

                    mByteBuffer.compact();
                    return new DataPack(data, appdata, ByteUtil.hexStr2bytes(command));
                } else {
                    // 不一致则回到“第二位”，继续找到下一个3AA3
                    mByteBuffer.position(frameStart + 2);
                }
            }

            // 最后清掉之前处理过的不合适的数据
            mByteBuffer.compact();
        } catch (Exception e) {
            // 最后清掉之前处理过的不合适的数据
            mByteBuffer.compact();
        }

        return null;

    }

}
